package com.cskaoyan.javase.oop3._3lambda._2reference;

import jdk.nashorn.internal.objects.NativeNumber;

/**
 * Lambda表达式的方法引用
 * Lambda表达式的抽象方法的实现可以直接指向一个已经存在的方法
 * 而不是自己书写实现。
 *
 * 那么什么样子的已存在方法,可以作为"Lambda表达式的抽象方法的实现"？
 * 只要该已存在的方法,能够满足抽象方法的重写规则就可以了.
 * 具体来说,对于功能接口中的抽象方法:
 *      返回值类型 方法名(形参列表);
 * 该已实现方法,应该满足:
 *      1.访问权限修饰符不重要,但是必须在写Lambda表达式的位置,具有权限
 *      2.static与非static不重要,因为这只会影响方法的调用,不影响它的实现
 *      3.返回值类型要和抽象方法中的返回值类型保持"兼容":
 *          a.基本数据类型和void,必须保持一致
 *          b.引用数据类型,父类返回父类类型,子类允许返回子类类型,当然也可以保持一致.
 *      4.方法名不重要,随便写.
 *      5.形参列表必须严格保持一致,但是要注意形参名不重要,随便写
 * 总之,该已经存在的方法,可以作为抽象方法的实现,重点是满足功能,其他的不重要.
 *
 * Lambda表达式方法引用的语法:
 *      1.(不推荐,了解即可)
 *          (形参列表) -> 已实现的方法(形参列表);
 *          解释:
 *              1.语法中"已实现的方法",应该写这个已实现方法,在这个位置的调用
 *                  如果是静态方法,类名点调用(同类中时,可以省略类名)
 *                  如果是成员方法,对象名点调用
 *              2.语法中的"形参列表",左右都需要完全保持一致.
 *
 *      2.(省略形参列表,省略运算符,推荐,最简洁)
 *      语法:
 *          方法的归属者::方法名;
 *          解释:
 *              a."::"是两个冒号组成
 *              b.方法的归属者:
 *                  静态方法属于类
 *                  成员方法属于对象
 *              c.语法中的方法名,直接写名字即可
 *                  不需要再写参数进去了
 *
 * @since 09:40
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        IA ia = str -> Demo.myTest(str);
        System.out.println(ia.test("我今天早上吃的是包子~"));
        System.out.println("----------------------");
        IA ia2 = str -> new Demo().test(str);
        System.out.println(ia2.test("我中午打算吃拉面~~"));
        System.out.println("-------------------");
        IB ib = Demo::method;
        Object stu = ib.test();
        if (stu instanceof Student) {
            Student s = (Student) stu;
            System.out.println(s.age);
            System.out.println(s.name);
        }
        System.out.println("--------------------");
        IB ib2 = new Demo()::method2;
        System.out.println(ib2.test());
    }

    // 作为接口IB中的抽象方法test的实现
    public static Student method() {
        System.out.println("我就是张三,我就是这样的法外狂徒~~");
        return new Student(18, "张三");
    }

    public Object method2() {
        System.out.println("我啥也不是,我就直接返回null~~");
        return null;
    }

    // 作为接口IA中的test抽象方法的实现
    private static String myTest(String string) {
        System.out.println("666");
        System.out.println("777");
        System.out.println("888");
        System.out.println(string);
        return "这是一个Lambda表达式指向的静态方法,作为它的实现!";
    }

    public String test(String str) {
        System.out.println(str);
        return "这是一个Lambda表达式指向的成员方法,作为它的实现!";
    }
}

class Student {
    int age;
    String name;

    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
}

@FunctionalInterface
interface IB {
    Object test();
}

@FunctionalInterface
interface IA {
    String test(String str);
}